﻿using System.Collections.Generic;

namespace TuxedoLib
{
	public static class Transform
	{
		internal static void Bookkeeping(int currentCounter)
		{
			counter = currentCounter;
			if ((counter & 512) == 0) // like every 8 seconds at 60 FPS
			{
				List<string> cleanupList = null;
				foreach (string key in cachedScale.Keys)
				{
					if (currentCounter - cachedScale[key][0][0] > 600)
					{
						if (cleanupList == null)
						{
							cleanupList = new List<string>() { key };
						}
						else
						{
							cleanupList.Add(key);
						}
					}
				}

				foreach (string key in cleanupList)
				{
					cachedScale.Remove(key);
				}
			}
		}

		private static int counter = 0;

		// {source width}:{source height}:{target width}:{target height} --> [counter of last used], [<target index> -> <source index> lookup]
		private static Dictionary<string, List<int[]>> cachedScale = new Dictionary<string, List<int[]>>();

		private static int[] GenerateTransformation(int sourceWidth, int sourceHeight, int targetWidth, int targetHeight)
		{
			int[] map = new int[targetWidth * targetHeight];
			int x, y, sx, sy, index;
			for (y = 0; y < targetHeight; ++y)
			{
				index = y * targetWidth;
				for (x = 0; x < targetWidth; ++x)
				{
					sx = x * sourceWidth / targetWidth;
					sy = y * sourceHeight / targetHeight;
					map[index++] = sy * sourceWidth + sx;
				}
			}
			return map;
		}

		public static void Scale(Image source, Image target)
		{
			string cacheKey = source.Width + ":" + source.Height + ":" + target.Width + ":" + target.Height;
			List<int[]> mapper;
			if (!cachedScale.TryGetValue(cacheKey, out mapper))
			{
				mapper = new List<int[]>() { new int[] { counter }, Transform.GenerateTransformation(source.width, source.height, target.width, target.height) };
				cachedScale[cacheKey] = mapper;
			}
			else
			{
				// update last-usage so that this doesn't get garbage collected
				cachedScale[cacheKey][0][0] = counter;
			}

			int[] targetPixels = target.pixels;
			int[] sourcePixels = source.pixels;

			int[] mapping = mapper[1];

			for (int index = targetPixels.Length - 1; index >= 0; --index)
			{
				targetPixels[index] = sourcePixels[mapping[index]];
			}
		}

		public static Image FlipHorizontal(Image source)
		{
			Image output = new Image(source.width, source.height);
			int[] targetPixels = output.pixels;
			int[] sourcePixels = source.pixels;

			output.colorKey = source.colorKey;
			output.useColorKey = source.useColorKey;
			output.useAlpha = source.useAlpha;

			int sourceIndex, targetIndex;
			int x;
			int width = source.width;
			for (int y = source.height - 1; y >= 0; --y)
			{
				sourceIndex = y * width;
				targetIndex = sourceIndex + width;
				for (x = width; x > 0; --x)
				{
					targetPixels[--targetIndex] = sourcePixels[sourceIndex++];
				}
			}

			return output;
		}
	}
}
